package cheme.Interpreter.AST.SystemSolver;

import java.util.Enumeration;

import cheme.Interpreter.AST.AstChemicalProcess;
import cheme.Interpreter.AST.Equation.AstEquation;
import cheme.Interpreter.AST.Interfaces.IAstChemicalProcess;
import cheme.Interpreter.AST.Interfaces.IAstEquation;
import cheme.Interpreter.AST.Interfaces.IAstExpression;
import cheme.Interpreter.AST.Interfaces.IAstIdentifier;
import cheme.Interpreter.AST.Interfaces.IAstNode;
import cheme.Interpreter.AST.Interfaces.IAstStatement;
import cheme.Interpreter.AST.Interfaces.IAstVariableDeclaration;
import cheme.Interpreter.AST.SymbolTable.SymbolTable;
import cheme.Interpreter.AST.Variable.AstIdentifier;
import cheme.Interpreter.AST.Variable.AstVariableDeclaration;

import syntaxtree.*;

/*
 * This guy has to: - Get the name of the variable by drilling down
 * Declaration->DeclarationDecoration->Identifier. - Get the declared value of
 * the variable by drilling down Declaration->Expression->...->LiteralFactor.
 * 
 * Along the way to entering a variable, (non-label) identifers are looked up in
 * the table. If the referrent does not exist a variable is created with a state
 * of InferredDeclaration and the relationship is established... - Get the type
 * of the variable by drilling down Declaration->Expression->TypeDecoration
 */
public class StreamDeclarationVisitor extends ChemicalVisitor
{

	public StreamDeclarationVisitor(SymbolTable symbolTable)
	{
		super(symbolTable);
	}

	/**
	 * f0 -> ( Statement() )* f1 -> <EOF>
	 */
	public IAstChemicalProcess visit(ChemicalProcess n, IAstNode argu)
	{
		IAstChemicalProcess process = new AstChemicalProcess();

		if(n.f0.present())
		{
			for(Enumeration<Node> e = n.f0.elements(); e.hasMoreElements();)
			{
				process.add(e.nextElement().accept(this, argu));
			}
		}
		
		return process;
	}

	/**
	 * f0 -> ( Declaration() | Equation() ) f1 -> <EOL>
	 */
	public IAstStatement visit(Statement n, IAstNode argu)
	{
		return (IAstStatement)n.f0.accept(this, argu);
	}
	   
	/**
	 * f0 -> StreamDeclaration()
	 */
	/**
	 * f0 -> DeclarationDecoration() f1 -> Expression()
	 */
	public IAstVariableDeclaration visit(OverallStreamDeclaration n, IAstNode argu)
	{
		return new AstVariableDeclaration(
				getSymbolTable(), 
				(IAstIdentifier)n.f0.f0.accept(this, argu), 
				(IAstExpression)n.f0.f1.accept(this, argu));
	}
	   
	/**
	 * f0 -> ">" f1 -> StreamDeclaration()
	 */
	public IAstVariableDeclaration visit(StreamComponentDeclaration n, IAstNode argu)
	{
		return new AstVariableDeclaration(
				getSymbolTable(), 
				(IAstIdentifier)n.f1.f0.accept(this, argu), 
				(IAstExpression)n.f1.f1.accept(this, argu));
	}

	/**
	 * f0 -> <IDENTIFIER> f1 -> ":"
	 */
	public IAstIdentifier visit(DeclarationDecoration n, IAstNode argu)
	{
		return new AstIdentifier(n.f0.tokenImage);
	}

	/**
	 * f0 -> Expression() f1 -> "=" f2 -> Expression()
	 */
	public IAstEquation visit(Equation n, IAstNode argu)
	{
		return new AstEquation(
				(IAstExpression)n.f0.accept(this, argu), 
				(IAstExpression)n.f2.accept(this, argu));
	}

	
}
